తెలుగు

టైప్‌స్క్రిప్ట్ 'ఇన్‌ఫర్' కీవర్డ్‌పై సమగ్ర గైడ్. శక్తివంతమైన టైప్ ఎక్స్‌ట్రాక్షన్ మరియు మానిప్యులేషన్ కోసం కండిషనల్ టైప్స్‌తో దీనిని ఎలా ఉపయోగించాలో అధునాతన ఉదాహరణలతో వివరిస్తుంది.

టైప్‌స్క్రిప్ట్ ఇన్‌ఫర్‌లో నైపుణ్యం: అధునాతన టైప్ మానిప్యులేషన్ కోసం కండిషనల్ టైప్ ఎక్స్‌ట్రాక్షన్

టైప్‌స్క్రిప్ట్ యొక్క టైప్ సిస్టమ్ చాలా శక్తివంతమైనది, ఇది డెవలపర్‌లను దృఢమైన మరియు నిర్వహించదగిన అప్లికేషన్‌లను సృష్టించడానికి అనుమతిస్తుంది. ఈ శక్తిని అందించే ముఖ్య లక్షణాలలో ఒకటి infer కీవర్డ్, దీనిని కండిషనల్ టైప్స్‌తో కలిపి ఉపయోగిస్తారు. ఈ కలయిక సంక్లిష్టమైన టైప్ స్ట్రక్చర్‌ల నుండి నిర్దిష్ట టైప్స్‌ను ఎక్స్‌ట్రాక్ట్ చేయడానికి ఒక యంత్రాంగాన్ని అందిస్తుంది. ఈ బ్లాగ్ పోస్ట్ infer కీవర్డ్ గురించి లోతుగా విశ్లేషిస్తుంది, దాని కార్యాచరణను వివరిస్తుంది మరియు అధునాతన వినియోగ సందర్భాలను ప్రదర్శిస్తుంది. API ఇంటరాక్షన్ నుండి సంక్లిష్ట డేటా స్ట్రక్చర్ మానిప్యులేషన్ వరకు విభిన్న సాఫ్ట్‌వేర్ డెవలప్‌మెంట్ దృశ్యాలకు వర్తించే ఆచరణాత్మక ఉదాహరణలను మనం అన్వేషిస్తాము.

కండిషనల్ టైప్స్ అంటే ఏమిటి?

మనం infer గురించి తెలుసుకునే ముందు, కండిషనల్ టైప్స్‌ను త్వరగా సమీక్షిద్దాం. టైప్‌స్క్రిప్ట్‌లోని కండిషనల్ టైప్స్, జావాస్క్రిప్ట్‌లోని టెర్నరీ ఆపరేటర్ మాదిరిగానే ఒక షరతు ఆధారంగా టైప్‌ను నిర్వచించడానికి మిమ్మల్ని అనుమతిస్తాయి. ప్రాథమిక సింటాక్స్ ఇది:

T extends U ? X : Y

దీనిని ఇలా చదవవచ్చు: "ఒకవేళ టైప్ T అనేది టైప్ U కు కేటాయించదగినది అయితే, అప్పుడు టైప్ X; లేకపోతే, టైప్ Y."

ఉదాహరణ:

type IsString<T> = T extends string ? true : false;

type StringResult = IsString<string>; // type StringResult = true
type NumberResult = IsString<number>; // type NumberResult = false

infer కీవర్డ్ పరిచయం

infer కీవర్డ్ ఒక కండిషనల్ టైప్ యొక్క extends క్లాజ్‌లో ఒక టైప్ వేరియబుల్‌ను ప్రకటించడానికి ఉపయోగించబడుతుంది, దీనిని తనిఖీ చేయబడుతున్న టైప్ నుండి ఇన్‌ఫర్ చేయవచ్చు. ముఖ్యంగా, ఇది ఒక టైప్‌లోని భాగాన్ని తర్వాత ఉపయోగం కోసం "పట్టుకోవడానికి" మిమ్మల్ని అనుమతిస్తుంది.

ప్రాథమిక సింటాక్స్:

type MyType<T> = T extends (infer U) ? U : never;

ఈ ఉదాహరణలో, T ఏదైనా ఒక టైప్‌కు కేటాయించదగినది అయితే, టైప్‌స్క్రిప్ట్ U యొక్క టైప్‌ను ఇన్‌ఫర్ చేయడానికి ప్రయత్నిస్తుంది. ఇన్‌ఫరెన్స్ విజయవంతమైతే, టైప్ U అవుతుంది; లేకపోతే, అది never అవుతుంది.

infer యొక్క సాధారణ ఉదాహరణలు

1. ఫంక్షన్ యొక్క రిటర్న్ టైప్‌ను ఇన్‌ఫర్ చేయడం

ఒక సాధారణ వినియోగ సందర్భం ఫంక్షన్ యొక్క రిటర్న్ టైప్‌ను ఇన్‌ఫర్ చేయడం:

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

function add(a: number, b: number): number {
  return a + b;
}

type AddReturnType = ReturnType<typeof add>; // type AddReturnType = number

function greet(name: string): string {
  return `Hello, ${name}!`;
}

type GreetReturnType = ReturnType<typeof greet>; // type GreetReturnType = string

ఈ ఉదాహరణలో, ReturnType<T> ఇన్‌పుట్‌గా ఫంక్షన్ టైప్ T ను తీసుకుంటుంది. ఇది T ఏదైనా ఆర్గ్యుమెంట్లను అంగీకరించి ఒక విలువను తిరిగి ఇచ్చే ఫంక్షన్‌కు కేటాయించదగినదా అని తనిఖీ చేస్తుంది. అలా అయితే, అది రిటర్న్ టైప్‌ను R గా ఇన్‌ఫర్ చేసి దానిని తిరిగి ఇస్తుంది. లేకపోతే, అది any ను తిరిగి ఇస్తుంది.

2. అర్రే ఎలిమెంట్ టైప్‌ను ఇన్‌ఫర్ చేయడం

మరొక ఉపయోగకరమైన దృశ్యం ఒక అర్రే నుండి ఎలిమెంట్ టైప్‌ను ఎక్స్‌ట్రాక్ట్ చేయడం:

type ArrayElementType<T> = T extends (infer U)[] ? U : never;

type NumberArrayType = ArrayElementType<number[]>; // type NumberArrayType = number
type StringArrayType = ArrayElementType<string[]>; // type StringArrayType = string
type MixedArrayType = ArrayElementType<(string | number)[]>; // type MixedArrayType = string | number
type NotAnArrayType = ArrayElementType<number>; // type NotAnArrayType = never

ఇక్కడ, ArrayElementType<T> T ఒక అర్రే టైప్ కాదా అని తనిఖీ చేస్తుంది. అలా అయితే, అది ఎలిమెంట్ టైప్‌ను U గా ఇన్‌ఫర్ చేసి దానిని తిరిగి ఇస్తుంది. కాకపోతే, అది never ను తిరిగి ఇస్తుంది.

infer యొక్క అధునాతన వినియోగ సందర్భాలు

1. కన్‌స్ట్రక్టర్ యొక్క పారామీటర్లను ఇన్‌ఫర్ చేయడం

మీరు ఒక కన్‌స్ట్రక్టర్ ఫంక్షన్ యొక్క పారామీటర్ టైప్స్‌ను ఎక్స్‌ట్రాక్ట్ చేయడానికి infer ను ఉపయోగించవచ్చు:

type ConstructorParameters<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;

class Person {
  constructor(public name: string, public age: number) {}
}

type PersonConstructorParams = ConstructorParameters<typeof Person>; // type PersonConstructorParams = [string, number]

class Point {
    constructor(public x: number, public y: number) {}
}

type PointConstructorParams = ConstructorParameters<typeof Point>; // type PointConstructorParams = [number, number]

ఈ సందర్భంలో, ConstructorParameters<T> ఒక కన్‌స్ట్రక్టర్ ఫంక్షన్ టైప్ T ను తీసుకుంటుంది. ఇది కన్‌స్ట్రక్టర్ పారామీటర్ల టైప్స్‌ను P గా ఇన్‌ఫర్ చేసి వాటిని ఒక టపుల్‌గా తిరిగి ఇస్తుంది.

2. ఆబ్జెక్ట్ టైప్స్ నుండి ప్రాపర్టీలను ఎక్స్‌ట్రాక్ట్ చేయడం

మ్యాప్డ్ టైప్స్ మరియు కండిషనల్ టైప్స్ ఉపయోగించి ఆబ్జెక్ట్ టైప్స్ నుండి నిర్దిష్ట ప్రాపర్టీలను ఎక్స్‌ట్రాక్ట్ చేయడానికి కూడా infer ను ఉపయోగించవచ్చు:

type PickByType<T, K extends keyof T, U> = {
  [P in K as T[P] extends U ? P : never]: T[P];
};

interface User {
  id: number;
  name: string;
  age: number;
  email: string;
  isActive: boolean;
}

type StringProperties = PickByType<User, keyof User, string>; // type StringProperties = { name: string; email: string; }

type NumberProperties = PickByType<User, keyof User, number>; // type NumberProperties = { id: number; age: number; }

//భౌగోళిక కోఆర్డినేట్‌లను సూచించే ఒక ఇంటర్‌ఫేస్.
interface GeoCoordinates {
    latitude: number;
    longitude: number;
    altitude: number;
    country: string;
    city: string;
    timezone: string;
}

type NumberCoordinateProperties = PickByType<GeoCoordinates, keyof GeoCoordinates, number>; // type NumberCoordinateProperties = { latitude: number; longitude: number; altitude: number; }

ఇక్కడ, PickByType<T, K, U> ఒక కొత్త టైప్‌ను సృష్టిస్తుంది, ఇందులో T యొక్క ప్రాపర్టీలలో (కీలు K లో ఉన్నవి) కేవలం U టైప్‌కు కేటాయించదగిన విలువలు ఉన్నవి మాత్రమే ఉంటాయి. మ్యాప్డ్ టైప్ T యొక్క కీలను ఇటరేట్ చేస్తుంది, మరియు కండిషనల్ టైప్ నిర్దిష్ట టైప్‌కు సరిపోలని కీలను ఫిల్టర్ చేస్తుంది.

3. ప్రామిసెస్‌తో పని చేయడం

మీరు ఒక Promise యొక్క రిసాల్వ్డ్ టైప్‌ను ఇన్‌ఫర్ చేయవచ్చు:

type Awaited<T> = T extends Promise<infer U> ? U : T;

async function fetchData(): Promise<string> {
  return 'Data from API';
}

type FetchDataType = Awaited<ReturnType<typeof fetchData>>; // type FetchDataType = string

async function fetchNumbers(): Promise<number[]> {
    return [1, 2, 3];
}

type FetchedNumbersType = Awaited<ReturnType<typeof fetchNumbers>>; //type FetchedNumbersType = number[]

Awaited<T> టైప్ ఒక టైప్ T ను తీసుకుంటుంది, ఇది ఒక ప్రామిస్ అని ఆశించబడుతుంది. అప్పుడు ఈ టైప్ ప్రామిస్ యొక్క రిసాల్వ్డ్ టైప్ U ను ఇన్‌ఫర్ చేసి, దానిని తిరిగి ఇస్తుంది. ఒకవేళ T ప్రామిస్ కాకపోతే, అది T ని తిరిగి ఇస్తుంది. ఇది టైప్‌స్క్రిప్ట్ యొక్క కొత్త వెర్షన్లలో ఒక అంతర్నిర్మిత యుటిలిటీ టైప్.

4. ప్రామిసెస్ అర్రే యొక్క టైప్‌ను ఎక్స్‌ట్రాక్ట్ చేయడం

Awaited మరియు అర్రే టైప్ ఇన్‌ఫరెన్స్‌ను కలపడం ద్వారా ప్రామిసెస్ అర్రే ద్వారా రిసాల్వ్ చేయబడిన టైప్‌ను మీరు ఇన్‌ఫర్ చేయవచ్చు. ఇది Promise.all తో వ్యవహరించేటప్పుడు ప్రత్యేకంగా ఉపయోగపడుతుంది.

type PromiseArrayReturnType<T extends Promise<any>[]> = {
    [K in keyof T]: Awaited<T[K]>;
};


async function getUSDRate(): Promise<number> {
  return 0.0069;
}

async function getEURRate(): Promise<number> {
  return 0.0064;
}

const rates = [getUSDRate(), getEURRate()];

type RatesType = PromiseArrayReturnType<typeof rates>;
// type RatesType = [number, number]

ఈ ఉదాహరణ మొదట రెండు అసమకాలిక ఫంక్షన్‌లను, getUSDRate మరియు getEURRate లను నిర్వచిస్తుంది, ఇవి ఎక్స్ఛేంజ్ రేట్లను పొందడాన్ని అనుకరిస్తాయి. అప్పుడు PromiseArrayReturnType యుటిలిటీ టైప్ అర్రేలోని ప్రతి Promise నుండి రిసాల్వ్డ్ టైప్‌ను ఎక్స్‌ట్రాక్ట్ చేస్తుంది, ఫలితంగా ఒక టపుల్ టైప్ వస్తుంది, ఇక్కడ ప్రతి ఎలిమెంట్ సంబంధిత ప్రామిస్ యొక్క అవైటెడ్ టైప్ అవుతుంది.

వివిధ రంగాలలో ఆచరణాత్మక ఉదాహరణలు

1. ఇ-కామర్స్ అప్లికేషన్

మీరు ఒక API నుండి ఉత్పత్తి వివరాలను పొందే ఒక ఇ-కామర్స్ అప్లికేషన్‌ను పరిగణించండి. మీరు ఉత్పత్తి డేటా యొక్క టైప్‌ను ఎక్స్‌ట్రాక్ట్ చేయడానికి infer ను ఉపయోగించవచ్చు:

interface Product {
  id: number;
  name: string;
  price: number;
  description: string;
  imageUrl: string;
  category: string;
  rating: number;
  countryOfOrigin: string;
}

async function fetchProduct(productId: number): Promise<Product> {
  // Simulate API call
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        id: productId,
        name: 'Example Product',
        price: 29.99,
        description: 'A sample product',
        imageUrl: 'https://example.com/image.jpg',
        category: 'Electronics',
        rating: 4.5,
        countryOfOrigin: 'Canada'
      });
    }, 500);
  });
}


type ProductType = Awaited<ReturnType<typeof fetchProduct>>; // type ProductType = Product

function displayProductDetails(product: ProductType) {
  console.log(`Product Name: ${product.name}`);
  console.log(`Price: ${product.price} ${product.countryOfOrigin === 'Canada' ? 'CAD' : (product.countryOfOrigin === 'USA' ? 'USD' : 'EUR')}`);
}

fetchProduct(123).then(displayProductDetails);

ఈ ఉదాహరణలో, మనం ఒక Product ఇంటర్‌ఫేస్ మరియు ఒక API నుండి ఉత్పత్తి వివరాలను పొందే fetchProduct ఫంక్షన్‌ను నిర్వచిస్తాము. fetchProduct ఫంక్షన్ యొక్క రిటర్న్ టైప్ నుండి Product టైప్‌ను ఎక్స్‌ట్రాక్ట్ చేయడానికి మనం Awaited మరియు ReturnType లను ఉపయోగిస్తాము, ఇది displayProductDetails ఫంక్షన్‌ను టైప్-చెక్ చేయడానికి మనకు అనుమతిస్తుంది.

2. ఇంటర్నషనలైజేషన్ (i18n)

మీకు ఒక అనువాద ఫంక్షన్ ఉందని అనుకుందాం, ఇది లోకేల్ ఆధారంగా వేర్వేరు స్ట్రింగ్‌లను తిరిగి ఇస్తుంది. టైప్ భద్రత కోసం ఈ ఫంక్షన్ యొక్క రిటర్న్ టైప్‌ను ఎక్స్‌ట్రాక్ట్ చేయడానికి మీరు infer ను ఉపయోగించవచ్చు:

interface Translations {
  greeting: string;
  farewell: string;
  welcomeMessage: (name: string) => string;
}

const enTranslations: Translations = {
  greeting: 'Hello',
  farewell: 'Goodbye',
  welcomeMessage: (name: string) => `Welcome, ${name}!`,
};

const frTranslations: Translations = {
  greeting: 'Bonjour',
  farewell: 'Au revoir',
  welcomeMessage: (name: string) => `Bienvenue, ${name}!`,
};

function getTranslation(locale: 'en' | 'fr'): Translations {
  return locale === 'en' ? enTranslations : frTranslations;
}

type TranslationType = ReturnType<typeof getTranslation>;

function greetUser(locale: 'en' | 'fr', name: string) {
  const translations = getTranslation(locale);
  console.log(translations.welcomeMessage(name));
}

greetUser('fr', 'Jean'); // Output: Bienvenue, Jean!

ఇక్కడ, TranslationType Translations ఇంటర్‌ఫేస్‌గా ఇన్‌ఫర్ చేయబడింది, ఇది greetUser ఫంక్షన్‌కు అనువదించబడిన స్ట్రింగ్‌లను యాక్సెస్ చేయడానికి సరైన టైప్ సమాచారం ఉందని నిర్ధారిస్తుంది.

3. API రెస్పాన్స్ హ్యాండ్లింగ్

APIలతో పని చేస్తున్నప్పుడు, రెస్పాన్స్ స్ట్రక్చర్ సంక్లిష్టంగా ఉండవచ్చు. నెస్ట్ చేయబడిన API రెస్పాన్స్‌ల నుండి నిర్దిష్ట డేటా టైప్స్‌ను ఎక్స్‌ట్రాక్ట్ చేయడానికి infer సహాయపడుతుంది:

interface ApiResponse<T> {
  status: number;
  data: T;
  message?: string;
}

interface UserData {
  id: number;
  username: string;
  email: string;
  profile: {
    firstName: string;
    lastName: string;
    country: string;
    language: string;
  }
}

async function fetchUser(userId: number): Promise<ApiResponse<UserData>> {
  // Simulate API call
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        status: 200,
        data: {
          id: userId,
          username: 'johndoe',
          email: 'john.doe@example.com',
          profile: {
            firstName: 'John',
            lastName: 'Doe',
            country: 'USA',
            language: 'en'
          }
        }
      });
    }, 500);
  });
}


type UserApiResponse = Awaited<ReturnType<typeof fetchUser>>;

type UserProfileType = UserApiResponse['data']['profile'];

function displayUserProfile(profile: UserProfileType) {
  console.log(`Name: ${profile.firstName} ${profile.lastName}`);
  console.log(`Country: ${profile.country}`);
}

fetchUser(123).then((response) => {
  if (response.status === 200) {
    displayUserProfile(response.data.profile);
  }
});

ఈ ఉదాహరణలో, మనం ఒక ApiResponse ఇంటర్‌ఫేస్ మరియు ఒక UserData ఇంటర్‌ఫేస్‌ను నిర్వచిస్తాము. API రెస్పాన్స్ నుండి UserProfileType ను ఎక్స్‌ట్రాక్ట్ చేయడానికి మనం infer మరియు టైప్ ఇండెక్సింగ్‌ను ఉపయోగిస్తాము, ఇది displayUserProfile ఫంక్షన్‌కు సరైన టైప్ అందుతుందని నిర్ధారిస్తుంది.

infer ఉపయోగించడానికి ఉత్తమ పద్ధతులు

సాధారణ ఆపదలు

infer కు ప్రత్యామ్నాయాలు

infer ఒక శక్తివంతమైన సాధనం అయినప్పటికీ, ప్రత్యామ్నాయ పద్ధతులు మరింత సముచితంగా ఉండే పరిస్థితులు ఉన్నాయి:

ముగింపు

టైప్‌స్క్రిప్ట్‌లోని infer కీవర్డ్, కండిషనల్ టైప్స్‌తో కలిపినప్పుడు, అధునాతన టైప్ మానిప్యులేషన్ సామర్థ్యాలను అన్‌లాక్ చేస్తుంది. ఇది సంక్లిష్ట టైప్ స్ట్రక్చర్‌ల నుండి నిర్దిష్ట టైప్స్‌ను ఎక్స్‌ట్రాక్ట్ చేయడానికి మిమ్మల్ని అనుమతిస్తుంది, తద్వారా మీరు మరింత దృఢమైన, నిర్వహించదగిన మరియు టైప్-సేఫ్ కోడ్‌ను వ్రాయగలుగుతారు. ఫంక్షన్ రిటర్న్ టైప్స్‌ను ఇన్‌ఫర్ చేయడం నుండి ఆబ్జెక్ట్ టైప్స్ నుండి ప్రాపర్టీలను ఎక్స్‌ట్రాక్ట్ చేయడం వరకు, అవకాశాలు విస్తారమైనవి. ఈ గైడ్‌లో వివరించిన సూత్రాలు మరియు ఉత్తమ పద్ధతులను అర్థం చేసుకోవడం ద్వారా, మీరు infer ను దాని పూర్తి సామర్థ్యానికి ఉపయోగించుకోవచ్చు మరియు మీ టైప్‌స్క్రిప్ట్ నైపుణ్యాలను ఉన్నత స్థాయికి తీసుకెళ్లవచ్చు. మీ టైప్స్‌ను డాక్యుమెంట్ చేయడం, వాటిని క్షుణ్ణంగా పరీక్షించడం మరియు తగినప్పుడు ప్రత్యామ్నాయ పద్ధతులను పరిగణించడం గుర్తుంచుకోండి. infer లో నైపుణ్యం సాధించడం నిజంగా వ్యక్తీకరణ మరియు శక్తివంతమైన టైప్‌స్క్రిప్ట్ కోడ్‌ను వ్రాయడానికి మీకు అధికారం ఇస్తుంది, ఇది చివరికి మెరుగైన సాఫ్ట్‌వేర్‌కు దారితీస్తుంది.